解決したいこと
【PHP】ポーカーの約判定について
PHPの勉強を始め、ポーカーの役判定の課題に直面しているのですが
ジョーカーありで役判定をすると全て判定結果がスリーカードになってしまいます。
当方、かなり知識も薄いためどこが原因かわからず手詰まり状態です。
ヒントだけでもいいので助けていただけますと嬉しいです。
よろしくお願いいたします。
発生している問題・エラー
全てスリーカード判定になってしまう
該当するソースコード
'heart', 'number'=>12],
['suit'=>'joker', 'number'=>0],
['suit'=>'spade', 'number'=>1],
['suit'=>'diamond', 'number'=>2],
['suit'=>'club', 'number'=>13],
];
// //ツーペア
// $cards = [
// ['suit'=>'heart', 'number'=>12],
// ['suit'=>'spade', 'number'=>10],
// ['suit'=>'joker', 'number'=>0],
// ['suit'=>'spade', 'number'=>1],
// ['suit'=>'club', 'number'=>1],
// ];
// //スリーカード
// $cards = [
// ['suit'=>'heart', 'number'=>7],
// ['suit'=>'spade', 'number'=>1],
// ['suit'=>'diamond', 'number'=>13],
// ['suit'=>'spade', 'number'=>7],
// ['suit'=>'joker', 'number'=>0],
// ];
// //ストレート
// $cards = [
// ['suit'=>'heart', 'number'=>3],
// ['suit'=>'spade', 'number'=>6],
// ['suit'=>'joker', 'number'=>0],
// ['suit'=>'spade', 'number'=>4],
// ['suit'=>'club', 'number'=>7],
// ];
// //フラッシュ
// $cards = [
// ['suit'=>'heart', 'number'=>2],
// ['suit'=>'heart', 'number'=>1],
// ['suit'=>'joker', 'number'=>13],
// ['suit'=>'heart', 'number'=>9],
// ['suit'=>'heart', 'number'=>4],
// ];
// //フルハウス
// $cards = [
// ['suit'=>'joker', 'number'=>0],
// ['suit'=>'spade', 'number'=>4],
// ['suit'=>'diamond', 'number'=>4],
// ['suit'=>'spade', 'number'=>7],
// ['suit'=>'club', 'number'=>7],
// ];
// //フォーカード
// $cards = [
// ['suit'=>'heart', 'number'=>8],
// ['suit'=>'spade', 'number'=>1],
// ['suit'=>'joker', 'number'=>0],
// ['suit'=>'spade', 'number'=>8],
// ['suit'=>'club', 'number'=>8],
// ];
//ストレートフラッシュ
// $cards = [
// ['suit'=>'heart', 'number'=>7],
// ['suit'=>'heart', 'number'=>11],
// ['suit'=>'heart', 'number'=>8],
// ['suit'=>'heart', 'number'=>10],
// ['suit'=>'joker', 'number'=>0],
// ];
// ロイヤルストレートフラッシュ
// $cards = [
// ['suit'=>'heart', 'number'=>12],
// ['suit'=>'heart', 'number'=>1],
// ['suit'=>'heart', 'number'=>13],
// ['suit'=>'joker', 'number'=>0],
// ['suit'=>'heart', 'number'=>10],
// ];
// 不正手札
// $cards = [
// ['suit'=>'heart', 'number'=>12],
// ['suit'=>'heart', 'number'=>12],
// ['suit'=>'heart', 'number'=>13],
// ['suit'=>'heart', 'number'=>11],
// ['suit'=>'joker', 'number'=>0],
// ];
function is_valid_hand($cards) {
// カードの不正チェック
$existing_cards = array(); // すでに存在するカードの組み合わせを格納する配列
foreach ($cards as $card) {
// 数字が0から13の範囲外の場合は不正
if ($card['number'] < 0 || $card['number'] > 13) {
return false;
}
// 絵柄が有効なものではない場合は不正
if ($card['suit'] !== 'heart' && $card['suit'] !== 'spade' && $card['suit'] !== 'diamond' && $card['suit'] !== 'club' && $card['suit'] !== 'joker') {
return false;
}
// 同じ絵柄と数字の組み合わせがすでに存在する場合は不正
$card_key = $card['suit'] . $card['number'];
if (in_array($card_key, $existing_cards)) {
return false;
} else {
// 組み合わせを配列に追加
$existing_cards[] = $card_key;
}
}
return true; // 全ての条件を満たす場合は正常
}
function compare_cards($cards){
global $suits_order;
foreach($cards as $key => $value)
{
$sort_keys[$key] = $value['number'];
}
array_multisort($sort_keys, SORT_ASC, $cards);
return $cards;
}
function is_royal_straight_flush($cards) {
// ロイヤルストレートフラッシュの数字の配列
$royal_flush_numbers = [1, 10, 11, 12, 13];
$suits = array_column($cards, 'suit');
$numbers = array_column($cards, 'number');
// ジョーカーを含むロイヤルストレートフラッシュの条件
$has_joker = in_array('joker', $suits) && count(array_intersect($royal_flush_numbers, $numbers)) === 4;
return ($numbers === $royal_flush_numbers) && (count(array_unique($suits)) === 1) || $has_joker;
}
function is_straight_flush($cards) {
$suits = array_column($cards, 'suit');
$numbers = array_column($cards, 'number');
// ジョーカーを除外した数字の配列
$numbers_without_joker = array_filter($numbers, function($number) {
return $number !== 0;
});
// ジョーカーが含まれている場合、最小の数字としてジョーカーの数字を扱う
if (in_array(0, $numbers)) {
$numbers_without_joker[] = max($numbers_without_joker) + 1; // 最小の数字よりも1大きい数字を追加する
}
// 数字を昇順にソート
sort($numbers_without_joker);
// 数字が連続しているかどうかを確認
$is_straight = true;
for ($i = 0; $i < count($numbers_without_joker) - 1; $i++) {
if ($numbers_without_joker[$i + 1] - $numbers_without_joker[$i] !== 1) {
$is_straight = false;
break;
}
}
// 同じスートかつ、連続した数字の場合はストレートフラッシュ
return $is_straight && (count(array_unique($suits)) === 1);
}
function is_four_of_a_kind($cards) {
$numbers = array_column($cards, 'number');
$count_values = array_count_values($numbers);
// Check if there are four cards of the same number
if (in_array(4, $count_values, true)) {
return true;
}
// Check if there are three cards of the same number and a joker
if (in_array(3, $count_values, true) && in_array(0, $numbers, true)) {
return true;
}
// Check if there are two cards of the same number and two jokers
if (in_array(2, $count_values, true) && in_array(0, $numbers, true) && count($numbers) === 3) {
return true;
}
return false;
}
function is_full_house($cards) {
$numbers = array_column($cards, 'number');
$count_values = array_count_values($numbers);
// Check if there are three cards of the same number and two cards of another number
if (in_array(3, $count_values, true) && in_array(2, $count_values, true)) {
return true;
}
// Check if there are two cards of the same number and a joker, and three cards of another number
if (in_array(2, $count_values, true) && in_array(0, $numbers, true) && count($numbers) === 3) {
return true;
}
// Check if there is a joker, and four cards of the same number
if (in_array(0, $numbers, true) && in_array(4, $count_values, true)) {
return true;
}
return false;
}
function is_flush($cards) {
$suits = array_column($cards, 'suit');
// If there's only one unique suit, it's a flush
if (count(array_unique($suits)) === 1) {
return true;
}
// If there's a joker, consider it as any suit
if (in_array('joker', $suits, true)) {
// Remove the joker from the suits array
$suits = array_diff($suits, ['joker']);
// If after removing the joker, there's only one unique suit left, it's a flush
if (count(array_unique($suits)) === 1) {
return true;
}
}
return false;
}
function is_straight($cards) {
$numbers = array_column($cards, 'number');
sort($numbers);
// If there are no duplicates and the difference between the highest and lowest card is 4, it's a straight
if (count(array_unique($numbers)) === 5 && ($numbers[4] - $numbers[0]) === 4) {
return true;
}
// If there's a joker, consider it as any number and check if it completes a straight
if (in_array(0, $numbers, true)) {
// Remove the joker from the numbers array
$numbers = array_diff($numbers, [0]);
sort($numbers);
// Check if the remaining cards form a straight
if (($numbers[3] - $numbers[0]) <= 3 && count(array_unique($numbers)) <= 4) {
return true;
}
}
return false;
}
function is_three_of_a_kind($cards) {
$numbers = array_column($cards, 'number');
$count_values = array_count_values($numbers);
// ジョーカーの数を数える
$joker_count = isset($count_values[0]) ? $count_values[0] : 0;
// ジョーカーを除外して、3枚揃っている数字が3回以上出現しているかどうかを確認
return isset($count_values[3 - $joker_count]) || $joker_count >= 3;
}
function is_two_pair($cards) {
$numbers = array_column($cards, 'number');
$joker_count = 0;
// ジョーカーの数を数える
foreach ($cards as $card) {
if ($card['number'] === 0) {
$joker_count++;
}
}
// ジョーカーを除外してカードの数字をカウント
$count_values = array_count_values(array_filter($numbers, function ($num) { return $num !== 0; }));
// ペアの数をカウント
$pairs = 0;
foreach ($count_values as $value) {
if ($value === 2) {
$pairs++;
}
}
// ジョーカーを利用してツーペアが成立するかどうかを判定
return ($pairs + $joker_count) === 2;
}
function is_one_pair($cards) {
$numbers = array_column($cards, 'number');
$joker_count = 0;
foreach ($cards as $card) {
if ($card['number'] === 0) { // ジョーカーの場合
$joker_count++;
}
}
$count_values = array_count_values(array_filter($numbers, function ($num) { return $num !== 0; })); // ジョーカーを除外してカウント
return in_array(2 - $joker_count, $count_values, true); // ペアがあるかどうかを確認
}
function judge($cards) {
//エラーチェック
$status = is_valid_hand($cards);
// カードの並び替え
$sort_data = compare_cards($cards);
// 手札が正常かどうかをチェック
if (!is_valid_hand($cards)) {
return "手札は不正です。";
}
// カードを数字でソート
$sorted_cards = compare_cards($cards);
// 役の判定を行う
if (is_royal_straight_flush($sorted_cards)) {
return "役はロイヤルストレートフラッシュです。";
} elseif (is_straight_flush($sorted_cards)) {
return "役はストレートフラッシュです。";
} elseif (is_four_of_a_kind($sorted_cards)) {
return "役はフォーカードです。";
} elseif (is_full_house($sorted_cards)) {
return "役はフルハウスです。";
} elseif (is_flush($sorted_cards)) {
return "役はフラッシュです。";
} elseif (is_straight($sorted_cards)) {
return "役はストレートです。";
} elseif (is_three_of_a_kind($sorted_cards)) {
return "役はスリーカードです。";
} elseif (is_two_pair($sorted_cards)) {
return "役はツーペアです。";
} elseif (is_one_pair($sorted_cards)) {
return "役はワンペアです。";
} else {
return "役はなしです。";
}
}
// 関数「judge」を呼び出して結果を表示する
echo "手札は" . "\n";
foreach ($cards as $card) {
echo $card['suit'] . $card['number'] . ' ';
}
echo "\n" . judge($cards) . "\n";
?>